﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.AccessControl;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
using Microsoft.Win32;
using FixSoft.CloudGround.Base;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
using FixSoft.Tools.Common;

namespace FixSoft.CloudGround
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {

        public static Settings Settings;
        public static string Path = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        private Options optionsWindow;
        public static PictureManager PictureManager;
        private DispatcherTimer timer;
        public static Translator Translator;
        //public static List<string> FilterKeywords;
        private string translatedKeyword;
        private string translatedFilter;
        private void ApplicationStartup(object sender, StartupEventArgs e)
        {
            if (e.Args.Contains("/enableoembg"))
            {
                EnableOEMBackground();
                Shutdown();
                return;
            }

            if (e.Args.Contains("/disableoembg"))
            {
                DisableOEMBackground();
                Shutdown();
                return;
            }

            if (e.Args.Contains("/createdirs"))
            {
                CreateDirs();
                Shutdown();
                return;
            }
            Settings = (Settings)XmlSerializable.Load(typeof(Settings), App.Path + "\\settings.conf") ?? NewSettings();

            System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(Settings.Language);
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(Settings.Language);

            AddIcon();

            if (App.Settings.ClearOldPics && Directory.Exists(Path + "\\Cache"))
            {
                foreach (var f in Directory.GetFiles(Path + "\\Cache"))
                {
                    if (File.GetCreationTime(f).CompareTo(DateTime.Now.AddDays(1 - App.Settings.ClearInterval)) <= 0)
                    {
                        File.Delete(f);
                    }
                }
            }

            PictureManager = new PictureManager();
            PictureManager.PictureDownloaded += PmanagerPictureDownloaded;
            PictureManager.PictureDownloading += PictureManager_PictureDownloading;


            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds((int)Settings.TimeMode * Settings.RefreshInterval);
            timer.Tick += TimerTick;

            if (Settings.DownloadAutomatically)
                timer.Start();

            Translator = new Translator();
            //Translator.Translated += TranslatorTranslated;
            WinAPI.SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
        }
        private Settings NewSettings()
        {
            Settings St = new Settings();
            St.Search = GetDefaultKeyword();
            return St;
        }
        static internal string GetDefaultKeyword()
        {
            switch (DateTime.Now.Month)
            {
                case 12:
                case 1:
                case 2:
                    return CloudGround.Properties.Resources.Winter;
                case 3:
                case 4:
                case 5:
                    return CloudGround.Properties.Resources.Spring;
                case 6:
                case 7:
                case 8:
                    return CloudGround.Properties.Resources.Summer;
                case 9:
                case 10:
                case 11:
                    return CloudGround.Properties.Resources.Autumn;
            }
            return "Clouds";
        }
        private void EnableOEMBackground()
        {
            try
            {
                using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows")
                    .OpenSubKey("CurrentVersion").OpenSubKey("Authentication").OpenSubKey("LogonUI").OpenSubKey("Background", true))
                {
                    key.SetValue("OEMBackground", 1, RegistryValueKind.DWord);
                    key.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Fix soft CloudGround Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void DisableOEMBackground()
        {
            try
            {
                using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software", RegistryKeyPermissionCheck.ReadWriteSubTree).OpenSubKey("Microsoft").OpenSubKey("Windows")
                    .OpenSubKey("CurrentVersion").OpenSubKey("Authentication").OpenSubKey("LogonUI").OpenSubKey("Background", true))
                {
                    key.DeleteValue("OEMBackground", false);
                    key.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Fix soft CloudGround Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void SetAccessRules()
        {
            DirectorySecurity dirSec = Directory.GetAccessControl(Environment.SystemDirectory + "\\oobe\\info\\backgrounds");
            dirSec.AddAccessRule(new FileSystemAccessRule(Environment.UserDomainName + "\\" + Environment.UserName, FileSystemRights.FullControl, AccessControlType.Allow));
            Directory.SetAccessControl(Environment.SystemDirectory + "\\oobe\\info\\backgrounds", dirSec);

        }

        private void CreateDirs()
        {
            if (!Directory.Exists(Environment.SystemDirectory + "\\oobe\\info"))
                Directory.CreateDirectory(Environment.SystemDirectory + "\\oobe\\info");
            if (!Directory.Exists(Environment.SystemDirectory + "\\oobe\\info\\backgrounds"))
                Directory.CreateDirectory(Environment.SystemDirectory + "\\oobe\\info\\backgrounds");
            SetAccessRules();
        }

        //void TranslatorTranslated(object sender, EventArgs e)
        //{
        //    App.PictureManager.GetPicture(Translator.Result);
        //}

        public static void Log(string message)
        {
            if (!Directory.Exists(App.Path + "\\Logs"))
                Directory.CreateDirectory(App.Path + "\\Logs");
            if (!File.Exists(App.Path + "\\Logs\\log.txt"))
            {
                File.WriteAllText(App.Path + "\\Logs\\log.txt", string.Empty);
            }

            try
            {
                File.AppendAllText(App.Path + "\\Logs\\log.txt",
                   DateTime.Now + " -------------- " + (char)(13) + (char)(10) + "OS: " + Environment.OSVersion.VersionString + (char)(13) + (char)(10) + message + (char)(13) + (char)(10));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can't write log. " + ex.Message);
            }
        }

        public static App CurrentApp
        {
            get
            {
                return (App)Current;
            }
        }

        internal void TimerTick(object sender, EventArgs e)
        {
            if (App.Settings.Language == "ru-RU" || App.Settings.Provider != "Rewalls")
                App.PictureManager.GetPicture(App.Settings.Search);
            else
            {
                if (string.IsNullOrEmpty(translatedKeyword))
                {
                    ThreadStart threadStarter = delegate
                                                    {
                                                        translatedKeyword = Translator.TranslateText(App.Settings.Search, "en|ru");
                                                        translatedFilter = Translator.TranslateText(App.Settings.Filter, "en|ru");
                                                        App.PictureManager.GetPicture(translatedKeyword, GetFilterKeyWords(translatedFilter));
                                                    };
                    var thread = new Thread(threadStarter);
                    thread.SetApartmentState(ApartmentState.STA);
                    thread.Start();
                }
                else
                    App.PictureManager.GetPicture(translatedKeyword);
            }
        }

        private static System.Windows.Forms.ContextMenu trayMenu;
        private static System.Windows.Forms.MenuItem closeMenuItem;
        private static System.Windows.Forms.MenuItem optionsMenuItem;
        private static System.Windows.Forms.MenuItem nextMenuItem;
        private static System.Windows.Forms.NotifyIcon trayIcon;

        public void AddIcon()
        {
            trayMenu = new System.Windows.Forms.ContextMenu();

            closeMenuItem = new System.Windows.Forms.MenuItem();
            closeMenuItem.Text = FixSoft.CloudGround.Properties.Resources.Close;
            closeMenuItem.Click += CloseMenuItemClick;

            optionsMenuItem = new System.Windows.Forms.MenuItem();
            optionsMenuItem.Text = FixSoft.CloudGround.Properties.Resources.Options;
            optionsMenuItem.Click += OptionsMenuItemClick;

            nextMenuItem = new System.Windows.Forms.MenuItem();
            nextMenuItem.Text = FixSoft.CloudGround.Properties.Resources.NextPicture;
            nextMenuItem.Click += new EventHandler(NextMenuItemClick);

            trayMenu.MenuItems.Add(nextMenuItem);
            trayMenu.MenuItems.Add(optionsMenuItem);
            trayMenu.MenuItems.Add(closeMenuItem);

            trayIcon = new System.Windows.Forms.NotifyIcon();

            var stream = GetResourceStream(new Uri("/Fix soft CloudGround;component/Resources/icon_small.ico", UriKind.Relative)).Stream;
            trayIcon.Icon = new Icon(stream); //System.Drawing.Icon.ExtractAssociatedIcon(Path + @"\Fix soft CloudGround.exe");
            stream.Close();
            trayIcon.Text = "Fix soft CloudGround";
            trayIcon.Visible = true;
            trayIcon.ContextMenu = trayMenu;
            trayIcon.DoubleClick += TrayIconClick;
        }
        void TrayIconClick(object sender, EventArgs e)
        {
            OptionsMenuItemClick(optionsMenuItem, EventArgs.Empty);
        }
        void NextMenuItemClick(object sender, EventArgs e)
        {
            TimerTick(null, EventArgs.Empty);
            if (Settings.DownloadAutomatically)
            {
                timer.Stop();
                timer.Start();
            }
            //if (App.Settings.Language == "ru-RU")
            //    App.PictureManager.GetPicture(App.Settings.Search);
            //else
            //{
            //    if (string.IsNullOrEmpty(Translator.Result))
            //        Translator.TranslateText(App.Settings.Search, "en|ru");
            //    else
            //        App.PictureManager.GetPicture(Translator.Result);
            //}
        }

        void OptionsMenuItemClick(object sender, EventArgs e)
        {
            if (optionsWindow != null && optionsWindow.IsVisible)
            {
                if (optionsWindow.WindowState == WindowState.Minimized)
                    optionsWindow.WindowState = WindowState.Normal;
                optionsWindow.Activate();
                return;
            }

            if (optionsWindow != null)
                optionsWindow.UpdateSettings -= OptionsWindowUpdateSettings;

            optionsWindow = new Options();
            optionsWindow.UpdateSettings += OptionsWindowUpdateSettings;
            optionsWindow.Closed += OptionsWindowClosed;

            if (App.Settings.Language == "he-IL" || App.Settings.Language == "ar-SA")
            {
                optionsWindow.FlowDirection = System.Windows.FlowDirection.RightToLeft;
            }
            else
            {
                optionsWindow.FlowDirection = System.Windows.FlowDirection.LeftToRight;
            }
            optionsWindow.ShowDialog();
        }

        void OptionsWindowClosed(object sender, EventArgs e)
        {
            optionsWindow.Closed -= OptionsWindowClosed;
            WinAPI.SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
        }

        void OptionsWindowUpdateSettings(object sender, EventArgs e)
        {
            translatedKeyword = string.Empty;
            translatedFilter = string.Empty;
            timer.Stop();
            timer.Interval = TimeSpan.FromMinutes(Settings.RefreshInterval);
            if (Settings.DownloadAutomatically)
                timer.Start();
        }

        public static List<string> GetFilterKeyWords(string filter)
        {
            List<string> nl = new List<string>();
            if (!string.IsNullOrEmpty(filter))
            {
                var s = filter.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries);
                if (s.Length == 0)
                    return nl;
                nl.AddRange(s);
                return nl;
            }
            else
            {
                return nl;
            }
        }

        void CloseMenuItemClick(object sender, EventArgs e)
        {
            trayIcon.Visible = false;
            trayIcon.Dispose();
            this.Shutdown();
        }
        public static string[] DownloadedIds
        {
            get
            {
                if (!Directory.Exists(App.Path + "\\Cache"))
                    Directory.CreateDirectory(App.Path + "\\Cache");
                string[] Images;
                Images = Directory.GetFiles(App.Path + "\\Cache");
                List<string> Ids;
                Ids = new List<string>();
                foreach (string ImageC in Images)
                {
                    Ids.Add(ImageC.Substring(ImageC.LastIndexOf("\\") + 1, (ImageC.LastIndexOf(".")) - (ImageC.LastIndexOf("\\") + 1)));
                }
                Ids.AddRange(GetFilterKeyWords(App.Settings.ExcludedPictures));
                return Ids.ToArray();
            }
        }
        internal static bool NothingFound;
        void PmanagerPictureDownloaded()
        {
            if (PictureManager.CurrentPicture != null && !NothingFound)
            {
                ChangePictureWithId(PictureManager.CurrentPicture.Id);
            }
            var stream = GetResourceStream(new Uri("/Fix soft CloudGround;component/Resources/icon_small.ico", UriKind.Relative)).Stream;
            trayIcon.Icon = new Icon(stream);
            stream.Close();
        }
        internal static void ChangePictureWithId(string Id)
        {
            ChangePicture(App.Path + "\\Cache\\" + Id.ToString() + ".jpg");
        }
        public void Activate()
        {
            OptionsMenuItemClick(this, EventArgs.Empty);
        }
        internal static void ExcludePicture(string Path)
        {
            if (System.IO.Path.GetDirectoryName(Path) == App.Path + "\\Cache")
                ExcludeWithId(PictureManager.GetId(Path));
        }
        internal static void ExcludeWithId(string Id)
        {
            List<string> Ep = GetFilterKeyWords(App.Settings.ExcludedPictures);
            foreach (string pic in Ep)
            {
                if (pic == Id)
                    return;
            }
            if (string.IsNullOrEmpty(App.Settings.ExcludedPictures))
            {
                App.Settings.ExcludedPictures = Id;
            }
            else
            {
                App.Settings.ExcludedPictures += "," + Id;
            }
            if (File.Exists(App.Path + "\\Cache\\" + Id + ".jpg"))
            {
                File.Delete(App.Path + "\\Cache\\" + Id + ".jpg");
            }
            App.Settings.Save(App.Path + "\\settings.conf");
        }
        static string LastId;
        static bool IsCurrentWallPaperDownloaded;
        internal static void ChangePicture(string PicturePath)
        {
            if (!File.Exists(PicturePath))
                return;
            FileInfo Fi = new FileInfo(PicturePath);
            if (Fi.Length == 0)
            {
                ExcludePicture(PicturePath);
                Fi.Delete();
                PictureManager.ChangePictureOffline();
                return;
            }
            if (Fi.DirectoryName == App.Path + "\\Cache")
            {
                LastId = System.IO.Path.GetFileNameWithoutExtension(PicturePath);
                IsCurrentWallPaperDownloaded = true;
            }
            else
            {
                IsCurrentWallPaperDownloaded = false;
            }
            WallPaperChanger.SetWallpaper(new Uri(PicturePath), WallPaperLayout.Stretched);
            // WinAPI.SystemParametersInfo(WinAPI.SPI_SETDESKWALLPAPER, 0, PicturePath, WinAPI.SPIF_UPDATEINIFILE).ToString();
            if (App.Settings.ChangeLogonBg)
            {
                if (!Directory.Exists(Environment.SystemDirectory + "\\oobe\\info") || !Directory.Exists(Environment.SystemDirectory + "\\oobe\\info\\backgrounds"))
                {
                    var p = new ProcessStartInfo { Verb = "runas", FileName = Assembly.GetExecutingAssembly().Location, Arguments = "/createdirs" };
                    var proc = Process.Start(p);
                    proc.WaitForExit();
                }
                var info = new FileInfo(PicturePath);
                if (info.Length > 0)
                {
                    File.Copy(PicturePath, Environment.SystemDirectory + "\\oobe\\info\\backgrounds\\backgroundDefault.jpg", true);
                    info = new FileInfo(Environment.SystemDirectory + "\\oobe\\info\\backgrounds\\backgroundDefault.jpg");
                    if (info.Length / 1024 > 256)
                    {
                        PictureManager.ReduceQuality(PicturePath, Environment.SystemDirectory + "\\oobe\\info\\backgrounds\\backgroundDefault.jpg", 90);
                    }
                }
            }
        }
        void PictureManager_PictureDownloading()
        {
            var stream = GetResourceStream(new Uri("/Fix soft CloudGround;component/Resources/icon_downloading.ico", UriKind.Relative)).Stream;
            trayIcon.Icon = new Icon(stream);
            stream.Close();
        }

        private void ApplicationDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            Log("Unhandled exception!");
            Log(e.Exception.ToString());
            MessageBox.Show(e.Exception.Message, "Fix soft CloudGround Error", MessageBoxButton.OK, MessageBoxImage.Error);
            e.Handled = true;
        }
    }
}
